package com.base.service.workflow.manager;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.base.core.context.utils.SpringUtils;
import com.base.core.head.constants.CodeResVal;
import com.base.core.head.enums.TaskTypeEnum;
import com.base.service.workflow.bo.ProcessStatusEnum;
import com.base.service.workflow.entity.DeploymentDO;
import com.base.service.workflow.entity.FlowDO;
import com.base.service.workflow.entity.ProcessDO;
import com.base.service.workflow.entity.TaskDO;
import com.base.service.workflow.service.AssignmentService;
import com.base.service.workflow.service.DeploymentService;
import com.base.service.workflow.service.FlowService;
import com.base.service.workflow.service.ProcessService;
import com.base.service.workflow.service.TaskService;
import com.gitee.magic.core.json.JsonObject;
import com.gitee.magic.framework.head.exception.BusinessException;

/**
 * @author start 
 */
@Service
public class ProcessManager {

	@Autowired
	private TaskService taskService;
	@Autowired
	private FlowService flowService;
	@Autowired
	private ProcessService processService;
	@Autowired
	private DeploymentService deploymentService;
	@Autowired
	private AssignmentService assignmentService;

	/**
	 * 创建流程实例
	 * @param processKey
	 * @param userId
	 * @param handleUserIds
	 * @param ccUserIds
	 * @param params
	 * @param bean
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
    public Long createInstance(
    		String processKey,
    		Long userId,List<Long> handleUserIds,List<Long> ccUserIds,JsonObject params,String bean) {
        DeploymentDO deployment = deploymentService.loadByProcessKey(processKey);
        if (deployment==null) {
            throw new BusinessException(CodeResVal.CODE_10051,processKey);
        }
		ProcessDefineService processDefine=(ProcessDefineService)SpringUtils.getBean(bean);
		if (deployment.getContent().getCc().isEmpty()) {
			ccUserIds.clear();
			ccUserIds.addAll(processDefine.queryAssigneeUserId(deployment.getContent().getCc()));
		}
		
		ProcessDO process = new ProcessDO();
        process.setUserId(userId);
        process.setDeploymentId(deployment.getId());
        process.setBean(bean);
        process.setStatus(ProcessStatusEnum.PENDING);
        process.setCcUserIds(ccUserIds);
        processService.save(process);
        processDefine.start(userId,process.getId());
        
        //find start event
		TaskDO currentTask=taskService.getTaskEvent(deployment.getId(),TaskTypeEnum.START_EVENT);
        TaskDO nextTask = taskService.nextTask(currentTask.getId(), params);
		FlowDO nextFlow = flowService.nextFlow(process.getId(),0L,nextTask, params);
        assignmentService.nextExecute(process,processDefine,userId,nextTask,nextFlow, handleUserIds,params);
        
        return process.getId();
    }
	
	/**
	 * 撤销
	 * @param processId
	 * @param description
	 */
	@Transactional(rollbackFor = Exception.class)
	public void undo(Long processId,String description) {
		ProcessDO process=processService.load(processId);
		if(process.getStatus()!=ProcessStatusEnum.PENDING) {
			throw new BusinessException(CodeResVal.CODE_10063);
		}
		processService.setStatus(processId, ProcessStatusEnum.UNDO);
		
		ProcessDefineService handle=(ProcessDefineService)SpringUtils.getBean(process.getBean());
		handle.execute(process.getUserId(),processId,ProcessStatusEnum.UNDO);
	}
	
}
